/*
 * Esta clase permite cifrar y decifrar datos con una 
 * frase que es personalizada por el programador y se
 * logra utilizando el MD5 y DES
 */
package system;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.sql.ResultSet;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

/**
 *
 * @author FAUSTO
 */
public class Cryptography {

    /**
     * Creates a new instance of encriptador
     */
    private static String passPhrase = "NHUj89yLN302RP334hUEzEFAGBIuuuSHEIOQ2883jjjf8802ug4mcm20e8fjd88439f2049N0QUjref8UEJERjsejffjvvmpe8880340JDOIR";
    private static byte[] SALT_BYTES = {
        (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
        (byte) 0x56, (byte) 0x35, (byte) 0xE3, (byte) 0x03
    };
    private static int ITERATION_COUNT = 19;
    private static String msg;
    private static ResultSet rsts;
    private static String exMsg;

    public String encryption(String str) {
        Cipher ecipher = null;
        Cipher dcipher = null;


        try {
            // Crear la key

            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
                    SALT_BYTES, ITERATION_COUNT);
            SecretKey key = SecretKeyFactory.getInstance(
                    "PBEWithMD5AndDES").generateSecret(keySpec);
            ecipher = Cipher.getInstance(key.getAlgorithm());
            dcipher = Cipher.getInstance(key.getAlgorithm());

            // Preparar los parametros para los ciphers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(
                    SALT_BYTES, ITERATION_COUNT);

            // Crear los ciphers
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        } catch (javax.crypto.NoSuchPaddingException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (java.security.NoSuchAlgorithmException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (java.security.InvalidKeyException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (InvalidKeySpecException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (InvalidAlgorithmParameterException ex) {
            setMsg("a0004", ex.getMessage());
        }

        try {
            // Encodear la cadena a bytes usando utf-8
            byte[] utf8 = str.getBytes("UTF8");

            // Encriptar
            byte[] enc = ecipher.doFinal(utf8);
            // Encodear bytes a base64 para obtener cadena
            return new sun.misc.BASE64Encoder().encode(enc);

        } catch (javax.crypto.BadPaddingException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (IllegalBlockSizeException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (UnsupportedEncodingException ex) {
            setMsg("a0004", ex.getMessage());
        }

        return null;
    }

    public String decryption(String str) {
        Cipher ecipher = null;
        Cipher dcipher = null;

        try {
            // Crear la key
            KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(),
                    SALT_BYTES, ITERATION_COUNT);
            SecretKey key = SecretKeyFactory.getInstance(
                    "PBEWithMD5AndDES").generateSecret(keySpec);
            ecipher = Cipher.getInstance(key.getAlgorithm());
            dcipher = Cipher.getInstance(key.getAlgorithm());

            // Preparar los parametros para los ciphers
            AlgorithmParameterSpec paramSpec = new PBEParameterSpec(
                    SALT_BYTES, ITERATION_COUNT);

            // Crear los ciphers
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
        } catch (javax.crypto.NoSuchPaddingException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (java.security.NoSuchAlgorithmException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (java.security.InvalidKeyException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (InvalidKeySpecException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (InvalidAlgorithmParameterException ex) {
            setMsg("a0004", ex.getMessage());
        }
        try {
            // Decodear base64 y obtener bytes

            byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);

            // Desencriptar

            byte[] utf8 = dcipher.doFinal(dec);

            // Decodear usando utf-8

            return new String(utf8, "UTF8");
        } catch (javax.crypto.BadPaddingException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (IllegalBlockSizeException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (UnsupportedEncodingException ex) {
            setMsg("a0004", ex.getMessage());
        } catch (java.io.IOException ex) {
            setMsg("a0004", ex.getMessage());
        }

        return null;
    }

    public String getMsg() {
        return msg;
    }

    public String getExMsg() {
        return exMsg;
    }

    public ResultSet getRsts() {
        return rsts;
    }

    /*
     * Gestiona los mensajes, que incluye: error del sistema, mensajes de la
     * aplicacion y respuesta del SQL
     */
    private static void setMsg(String data1, String data2) {
        msg = data1;
        exMsg = data2;
    }
}
